package com.davfx.httpnio;

import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.spi.SelectorProvider;
import java.util.Iterator;
import java.util.LinkedList;

import com.davfx.util.Log;

public final class ThreadSafeWorker implements Worker, Runnable {
	private final Selector selector;
	private LinkedList<SelectorVisitor> queue = new LinkedList<SelectorVisitor>();
	private boolean closed = false;

	public ThreadSafeWorker() throws IOException {
		selector = SelectorProvider.provider().openSelector();
	}
	
	public void close() {
		add(new SelectorVisitor() {
			@Override
			public void visit(Selector selector) {
				closed = true;
			}
		});
	}
	
	public void add(SelectorVisitor visitor) {
		synchronized (queue) {
			queue.addLast(visitor);
		}
		selector.wakeup();
	}
	
	public void run() {
		try {
			while (true) {
				LinkedList<SelectorVisitor> q;
				synchronized (queue) {
					q = queue;
					queue = new LinkedList<SelectorVisitor>();
				}
				for (SelectorVisitor v : q) {
					v.visit(selector);
				}
				if (closed) {
					break;
				}
				selector.select();
				Iterator<SelectionKey> i = selector.selectedKeys().iterator();
				while (i.hasNext()) {
					SelectionKey key = i.next();
					i.remove();
					((SelectionKeyVisitor) key.attachment()).visit(key);
				}
			}
		} catch (IOException e) {
			Log.error("Server error", e);
		}
	}
}
